#include"./show-bytes.h"
/// @brief 按照存储顺序输出pointer指向值的16进制显示
/// @param pointer 要输出内容的指针
/// @param size 要输出内容的字节数
void show_bytes(void* pointer,size_t size){
    byte_pointer start=(byte_pointer)pointer;
    size_t i;
    for(i=0;i<size;i++)
        printf("%X ",start[i]);
    printf("\n");
}
void show_short(short x){
    show_bytes(&x,sizeof(short));
}
void show_int(int x){
    show_bytes(&x,sizeof(int));
}
void show_long(long x){
    show_bytes(&x,sizeof(long));
}
void show_double(double x){
    show_bytes(&x,sizeof(double));
}
/// @brief 检测当前机器是不是小端序
/// @return 1是，0不是
int is_little_end(){
    short num=0x0001;
    byte_pointer bp=(byte_pointer)&num;
    return bp[0];
}
/// @brief 把words的第pos（0开始）个字节替换为word
/// @param words 要替换的序列
/// @param pos 位置从0开始，低位开始
/// @param word 替换内容
/// @return 替换完成的序列
unsigned replace_byte(unsigned words,int pos,unsigned char word){//无需考虑大小端序C已经自动转化
    //错误检查
    if(pos<0||pos>sizeof(unsigned)-1){
        printf("pos is error!");
    }
    //8位是1字节，<<3 相当于*8
    unsigned mask=0xff;
    mask=mask<<(pos<<3);
    unsigned pos_byte=((unsigned) word)<<(pos<<3);
    return ~mask&words|pos_byte;
}
/// @brief 检测整形右移运算是否是算术右移
/// @return 1算数，0非算数
int shifts_are_arithmetic(){
    //把int设置为0xff...f
    int num=-1;
    //右移w-1位
    //num>>=(sizeof(int)<<3-1);
    //如果是算数此时还是0xff...f
    //return !(~num);
    return !(num^(num>>1));
}
/// @brief 用算术右移实现逻辑右移
/// @param x 要右移的数
/// @param k 右移的位数
/// @return 结果
unsigned srl(unsigned x, int k){
    //算术右移后的数
    unsigned xsra = (int) x >> k;
    //逻辑右移左端一直补0，让左边k位强制为0即可
    int w=sizeof(int)<<3;
    int mask=-1<<(w-k);//左边k位设置为1
    return xsra&~mask;
}
/// @brief 用逻辑右移实现算术右移
/// @param x 要右移的数
/// @param k 右移的位数
/// @return 结果
int sra(int x, int k){
    //逻辑右移后的结果
    int xsrl = (unsigned) x >> k;
    //逻辑右移要提取符号位
    int w=sizeof(int)<<3;
    int flag_mask=1<<(w-1);
    //(flag_mask&x);//负数为1，正数为0
    int mask=(int)-1<<(w-k);//左边k位设置为1
    mask&=!(flag_mask&x)-1;//mask在负数时&-1，正数时&0
    return mask|xsrl;
}
/// @brief 判断num的二进制数中是否有奇数个一
/// @param num 要判断的数
/// @return 奇数个（1），偶数个（0）
int odd_ones(unsigned num){
    /*
    1.异或的时候1的个数总是成对减少（也就是说异或之前两边一共有奇（偶）数个一结果就有奇（偶）数个一）
    2.偶数个1对半异或后两边永远是偶数，奇数个1对半抑或后两边永远是奇数
    3.最后剩下1个位奇数是奇数个1，肯定就是1
    ...
    */
    num^=num>>16;
    num^=num>>8;
    num^=num>>4;
    num^=num>>2;
    num^=num>>1;
    num&=(unsigned)0x1;
    return num;
}
/// @brief 只保留最左边的1其他都设为0
/// @param num 数值
/// @return 修改后的数值
unsigned leftmost_one(unsigned num){
    num|=num>>1;
    num|=num>>2;
    num|=num>>4;
    num|=num>>8;
    num|=num>>16;
    //至此第一个1后面都变成了1，而进位可以把后边的1干掉,0的话是全0
    //num>>1+1（0的话不需要加）
    return (num>>1)+(num&&1);
}
/// @brief 如果是32位的整数就返回1
/// @return 
int int_size_is_32(){
    int num=1<<31;
    int beyond=num<<1;
    return num&&!beyond;
}
/// @brief 生成一个数，从第x位往后都是1
/// @param x 从1开始
/// @return 生成的数
int lower_one_mask(int x){
    int w=sizeof(x)<<3;
    return (unsigned)-1>>(w-x);
}
/// @brief 循环左移
/// @param x 要左移的数
/// @param n 0<=n<w
/// @return 移动完的数
unsigned rotate_left(unsigned x,int n){
    int w=sizeof(unsigned)<<3;
    //防止超出w导致警告或不确定问题
    return x<<n|(x>>(w-1-n)>>1);
}